Générateur de faux français

Nous allons créer un générateur de faux français capable de s'entraîner en lisant des livres. En partant d'un long texte il est possible d'étudier statistiquement la répartition des lettres pour écrire automatiquement une oeuvre... qui n'aura certainement pas beaucoup de sens.
Nous allons suivre plusieurs étapes pour réaliser ce programme :

ILecture d'un long texte

Créer un nouveau fichier faux_français.py .
Pour lire un fichier, il faut d'abord l'ouvrir et retenir sa référence dans la variable f en tapant :
f=open("dossiers/nom_du_fichier.txt",'r')
Une fois ouvert, pour lire son contenu entièrement et l'affecter à une variable :
contenu=f.read()
Ne pas oublier de fermer le fichier pour éviter les mauvaises surprises :
f.close()
Le 'r' dans open signifie "read", c'est à dire que le fichier ne sera ouvert qu'en écriture. Pour modifier le fichier, il faut mettre 'w' (write).
  • Télécharger un des textes suivant et l'enregistrer dans le même dossier que votre programme : Le seigneur des anneaux - tome 1 , Une vie
  • Lire le fichier entier et le stocker dans une variable txt
  • Créer un dictionnaire appelé (lettres) dont les clés sont les lettres du texte et dont les valeurs sont le nombre d'occurence de la lettre dans le texte.
  • Utiliser os.open() et os.read() pour lire le fichier.
  • Créer un dictionnaire vide lettres={}
  • Ecrire une boucle sur les caractères de txt de la manière suivante :
    for c in txt:
        ...
    c sera le caractère visité.
  • Pour vérifier si c est déjà dans le dictionnaire lettres , utiliser in . Si il y est, on peut incrémenter la valeur de lettres[c]
La variable lettres devrait ressembler à {'j':4670, 'r':61280, ...}

IITable des transitions

Nous souhaitons créer la table des transitions, c'est à dire le tableau comptant, pour chaque lettre, le nombre de ses successeurs possibles :

a b ... z
a \(N_{a\rightarrow a}\) \(N_{a\rightarrow b}\) ... \(N_{a\rightarrow z}\)
b \(N_{b\rightarrow a}\) \(N_{b\rightarrow b}\) ... \(N_{b\rightarrow z}\)
... ... ... ... ...
z \(N_{z\rightarrow a}\) \(N_{z\rightarrow b}\) ... \(N_{z\rightarrow z}\)
où \(N_{x\rightarrow y}\) est le nombre de fois que la lettre '\(x\)' est suivi de la lettre '\(y\)'.

Dans notre cas, il y aura plus de 26 entrées à ce tableau car le texte contient majuscules, espaces, ponctuations et sauts de lignes (représentés par '\n')

Nous représenterons cette table par un dictionnaire table dont les clés sont les lettres du texte et les valeurs un autre dictionnaire dont les clés sont les succésseurs et les valeurs sont leur nombre.

La table de transition ressemblera à :
table = {
     'J':{"'": 254, '.': 1, 'a': 15, 'e': 790, 'o': 23, 'u': 25, '’': 1},
    ...
     'a': {' ': 7, ' ': 206, ',': 1, 'C': 2, 'D': 6, ... },
}

Cela signifie que la lettre 'J' est suivie 254 fois d'une apostrophe, une fois d'un point, 15 fois de la lettre 'a', etc.

La lettre 'a' est suivie 7 fois d'un saut de ligne, 206 fois d'un espace, etc.

Créer un dictionnaire appelé (table) qui donne la table des transitions
  • Créer un dictionnaire vide table={}
  • Ecrire une boucle sur i allant de 0 à len(txt)-1 la longueur (moins un) du texte de la manière suivante :
    for i in range(0,len(txt)):
        ...
    i sera la position du caractère visité et i+1 la position du suivant.
  • Si on appelle c1 le caractère visité et c2 le caractère suivant, la valeur de table[c1][c2] contient le nombre de fois que le caractère c2 suit le caractère c1 .
  • Comme pour lettres , faire attention à initialiser table[c1]={} au bon moment.
  • Comme pour lettres , vérifier si c2 est dans table[c1] avant d'incrémenter table[c1][c2] .

IIITirer une lettre au hasard

Afin de simuler le hasard, nous allons utiliser la bibliothèque random . Pour cela, il faut ajouter import random au début du programme
Importer la bibliothèque import random dans votre fichier.
Le module random permet notamment de :
  • Tirer un flottant au hasard entre 0 et 1 : random.random()
  • Tirer un nombre entier au hasard entre deux valeurs \(n\) et \(m\) : random.randint(n,m)
  • Choisir un élément au hasard dans une liste L donnée : random.choice(L)
  • Choisir un élément au hasard dans une liste L donnée : random.choice(L)
Dans la console, importer import random puis :
  • Ecrire une commande qui permet de tirer à 'pile' ou 'face'
  • Ecrire une commande qui permet de tirer une lettre de l'alphabet au hasard
Les commandes précédents font des tirages uniformes. Il faudra programmer un peu pour tenir compte des pondérations de notre table.
Créer une fonction choix(T,n) qui prend comme arguments T la table des transitions d'une lettre et n le nombre total de transitions et qui renvoie une lettre tirée au hasard en respectant les pondérations.
Pour T={'a':2, 'b':1, 'c':'3'} et n=5 , la fonction renverra 'a', 'b' ou 'c' avec les probabilités de \(\frac{2}{5}\), \(\frac{1}{5}\) et \(\frac{3}{5}\).
Le total n pourrait se calculer à partir de T , mais comme il est donné dans notre cas par les valeurs de lettres , le mettre en argument évitera de le recalculer inutilement plusieurs fois.
L'idée est de tirer un nombre entier i au hasard entre 0 et n et de balayer la table de transition pour voir au niveau de quelle lettre on tombe.
En reprenant l'exemple précédent, on va tirer un nombre au hasard entre 0 et 5. Par exemple 4. On parcourt alors la table :
a b c
2 1 3
  • Pour 'a' : 2 <4 donc on continue.
  • Pour 'b' : 2+1=3<4 donc on continue.
  • Pour 'c' : 3 + 3 ≥ 6 donc on renvoie 'c'
def choix(T,n):
    r=random.randint(0,n)
    k=0
    for c in T:
        k=k+T[c]
        if k>=n:
        return c
    return c

IVGénérer un texte

Il ne reste qu'à exploiter la table de transitions table et la fonction choix :

Créer une fonction generateur(lettres,table,N) qui prend comme arguments lettres le dictionnaire comptant les lettres, table la table des transitions des lettres, N un entier et qui renvoie un texte aléatoire de N caractères.
  • On commence par une lettre c tirée au hasard
  • Il va falloir faire une boucle de N itération
  • A chaque étape, on tire au hasard la nouvelle lettre à l\'aide de choix table[c] et lettres[c] (le nombre de transitions).
  • A l'étape suivante, on prend la lettre précédemment tirée comme point de départ.

VAller plus loin

On peut imaginer des moyens simples d'améliorer la qualité du texte généré aléatoirement en modifiant quelques éléments :